home *** CD-ROM | disk | FTP | other *** search
/ GFX Sensations 1 / Graphic Sensations - Volume 1.iso / tools / amiga / 3d_tools / irit40s.lha / Irit / cagd_lib / bspcoxdb.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-30  |  5.1 KB  |  116 lines

  1. /******************************************************************************
  2. * BspCoxDB.c - Bspline evaluation using Cox - de Boor recursive algorithm.    *
  3. *******************************************************************************
  4. * Written by Gershon Elber, Aug. 90.                          *
  5. ******************************************************************************/
  6.  
  7. #include <ctype.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include "cagd_loc.h"
  11.  
  12. /******************************************************************************
  13. * Returns a pointer to a static data, holding the value of the curve at given *
  14. * parametric location t. The curve is assumed to be non uniform spline.          *
  15. * Uses the recursive Cox de Boor algorithm, to evaluate the spline.          *
  16. ******************************************************************************/
  17. CagdRType *BspCrvEvalCoxDeBoor(CagdCrvStruct *Crv, CagdRType t)
  18. {
  19.     static CagdRType Pt[CAGD_MAX_PT_COORD];
  20.     CagdBType
  21.     IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
  22.     CagdRType *p, *BasisFunc;
  23.     int i, j, l, IndexFirst,
  24.     k = Crv -> Order,
  25.     MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
  26.  
  27.     BasisFunc = BspCrvCoxDeBoorBasis(Crv -> KnotVector, k, Crv -> Length,
  28.                                      t, &IndexFirst);
  29.  
  30.     /* And finally multiply the basis functions with the control polygon. */
  31.     for (i = IsNotRational; i <= MaxCoord; i++) {
  32.     Pt[i] = 0;
  33.     p = Crv -> Points[i];
  34.     for (j = IndexFirst, l = 0; l < k; )
  35.         Pt[i] += p[j++] * BasisFunc[l++];
  36.     }
  37.  
  38.     return Pt;
  39. }
  40.  
  41. /******************************************************************************
  42. * Returns a pointer to a vector of size order, holding values of the non zero *
  43. * basis functions of a given curve at given parametric location t.          *
  44. * This vector SHOULD NOT BE FREED. Although it is dynamically allocated, the  *
  45. * returned pointer does not point to the beginning of this memory and it will *
  46. * be maintained by this routine (i.e. it will be freed next time this routine *
  47. * is called).                                      *
  48. * IndexFirst returns the index of first non zero basis function for given t.  *
  49. * The curve is assumed to be non uniform bspline.                  *
  50. * Uses the recursive Cox de Boor algorithm, to evaluate the spline.          *
  51. * Algorithm:                                      *
  52. * Use the following recursion relation with B(i,0) == 1.                      *
  53. *                                          *
  54. *          t     -    t(i)            t(i+k)    -   t                         *
  55. * B(i,k) = --------------- B(i,k-1) + --------------- B(i+1,k-1)              *
  56. *          t(i+k-1) - t(i)            t(i+k) - t(i+1)                         *
  57. *                                          *
  58. * Starting with constant spline (k == 1) only one basis func. is non zero and *
  59. * equal to one. This is the constant spline spanning interval t(i)..t(i+1)    *
  60. * such that t(i) <= t and t(i+1) > t. We then raise this constant spline      *
  61. * to the Crv order and finding in this process all the basis functions that   *
  62. * are non zero in t for order Order. Sound limple hah!?                  *
  63. ******************************************************************************/
  64. CagdRType *BspCrvCoxDeBoorBasis(CagdRType *KnotVector, int Order, int Len,
  65.                         CagdRType t, int *IndexFirst)
  66. {
  67.     static CagdRType *B = NULL;
  68.     CagdRType s1, s2, *BasisFunc;
  69.     int i, l,
  70.     KVLen = Order + Len,
  71.     Index = BspKnotLastIndexLE(KnotVector, KVLen, t);
  72.  
  73.     if (!BspKnotParamInDomain(KnotVector, Len, Order, t))
  74.     FATAL_ERROR(CAGD_ERR_T_NOT_IN_CRV);
  75.  
  76.     /* Starting the recursion from constant splines - one spline is non     */
  77.     /* zero and is equal to one. This is the spline that starts at Index.   */
  78.     /* As We are going to reference index -1 we increment the buffer by one */
  79.     /* and save 0.0 at index -1. We then initialize the constant spline     */
  80.     /* values - all are zero but the one from t(i) to t(i+1).               */
  81.     if (B != NULL)
  82.     IritFree((VoidPtr) B);
  83.     BasisFunc = B = (CagdRType *) IritMalloc(sizeof(CagdRType) * (1 + Order));
  84.     *BasisFunc++ = 0.0;
  85.     if (Index >= Len + Order - 1) {
  86.     /* We are at the end of the parametric domain and this is open      */
  87.     /* end condition - simply return last point.                */
  88.     for (i = 0; i < Order; i++)
  89.         BasisFunc[i] = (CagdRType) (i == Order - 1);
  90.  
  91.     *IndexFirst = Len - Order;
  92.     return BasisFunc;
  93.     }
  94.     else
  95.     for (i = 0; i < Order; i++)
  96.         BasisFunc[i] = (CagdRType) (i == 0);
  97.  
  98.     /* Here is the tricky part. we raise these constant splines to the      */
  99.     /* required order of the curve Crv for the given parameter t. There are */
  100.     /* at most order non zero function at param. value t. These functions   */
  101.     /* start at Index-order+1 up to Index (order functions overwhole).      */
  102.     for (i = 2; i <= Order; i++) {            /* Goes through all orders... */
  103.     for (l = i - 1; l >= 0; l--) {  /* And all basis funcs. of order i. */
  104.         s1 = (KnotVector[Index + l] - KnotVector[Index + l - i + 1]);
  105.         s1 = APX_EQ(s1, 0.0) ? 0.0 : (t - KnotVector[Index + l - i + 1]) / s1;
  106.         s2 = (KnotVector[Index + l + 1] - KnotVector[Index + l - i + 2]);
  107.         s2 = APX_EQ(s2, 0.0) ? 0.0 : (KnotVector[Index + l + 1] - t) / s2;
  108.  
  109.         BasisFunc[l] = s1 * BasisFunc[l - 1] + s2 * BasisFunc[l];
  110.     }
  111.     }
  112.  
  113.     *IndexFirst = Index - Order + 1;
  114.     return BasisFunc;
  115. }
  116.